#
# Copyright 2013 - Tom Alessi
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


"""Form and Form Field classes for the Berper project

"""

import re
from django import forms
from django.core.validators import URLValidator
from django.core.exceptions import ValidationError
from berper.main.models import Scan


### FORMS ###


class ConfigForm(forms.Form):
    """Form for updating configs"""

    scan_threads = forms.IntegerField(required=False)
    java = forms.CharField(required=False)
    burpjar = forms.CharField(required=False)
    mysql_java = forms.CharField(required=False)
    burp_memory = forms.CharField(required=False)
    burp_reports = forms.EmailField(required=False)
    filter = forms.CharField(required=False)

    # We need access to some of the update_ values, but only some.
    update_java = forms.BooleanField(required=False)
    update_burpjar = forms.BooleanField(required=False)
    update_mysql_java = forms.BooleanField(required=False)
    update_burpreports = forms.BooleanField(required=False)

    # Override the form clean method - there is some special logic to validate 

    def clean(self):
        cleaned_data = super(ConfigForm, self).clean()
        update_java = cleaned_data.get('update_java')
        update_burpjar = cleaned_data.get('update_burpjar')
        update_mysql_java = cleaned_data.get('update_mysql_java')
        update_burpreports = cleaned_data.get('update_burpreports')

        # Return the full collection of cleaned data
        return cleaned_data


class SchedulerForm(forms.Form):
    """Form for managing the scan schedule"""

    enabled = forms.BooleanField(required=False)


class AddSScanForm(forms.Form):
    """Form for adding a spidered scan"""

    name = forms.CharField(required=True)
    site = forms.CharField(required=True)
    hport = forms.IntegerField(required=False)
    sport = forms.IntegerField(required=False)
    time = forms.TimeField(required=True,input_formats=['%H:%M'])
    monday = forms.BooleanField(required=False)
    tuesday = forms.BooleanField(required=False)
    wednesday = forms.BooleanField(required=False)
    thursday = forms.BooleanField(required=False)
    friday = forms.BooleanField(required=False)
    saturday = forms.BooleanField(required=False)
    sunday = forms.BooleanField(required=False)
    method = forms.BooleanField(required=False)
    seed = forms.CharField(required=True)
    enabled = forms.BooleanField(required=False)

    # Override the form clean method
    #  - make sure the scan name does not already exist
    #  - make sure at least one port was selected

    def clean(self):
		cleaned_data = super(AddSScanForm, self).clean()
		name = cleaned_data.get('name')
		hport = cleaned_data.get('hport')
		sport = cleaned_data.get('sport')
		monday = cleaned_data.get('monday')
		tuesday = cleaned_data.get('tuesday')
		wednesday = cleaned_data.get('wednesday')
		thursday = cleaned_data.get('thursday')
		friday = cleaned_data.get('friday')
		saturday = cleaned_data.get('saturday')
		sunday = cleaned_data.get('sunday')

		# Ensure the scan name does not already exist
		if Scan.objects.filter(name=name):
			self._errors["name"] = self.error_class(['That name already exists'])

		# Ensure at least one day was selected (just show the error on monday)
		if not monday and not tuesday and not wednesday and not thursday and not friday and not saturday and not sunday:
			self._errors["monday"] = self.error_class(['Select at least one day'])

		# There must be at least an hport or an sport
		if not hport and not sport:
			self._errors["hport"] = self.error_class(['an HTTP or HTTPS port must be defined'])
			self._errors["sport"] = self.error_class(['an HTTP or HTTPS port must be defined'])

		# Return the full collection of cleaned data
		return cleaned_data  


class ModifySScanForm(forms.Form):
    """Form for modifying a spidered scan"""

    id = forms.IntegerField(required=True)
    hport = forms.IntegerField(required=False)
    sport = forms.IntegerField(required=False)
    time = forms.TimeField(required=True,input_formats=['%H:%M'])
    monday = forms.BooleanField(required=False)
    tuesday = forms.BooleanField(required=False)
    wednesday = forms.BooleanField(required=False)
    thursday = forms.BooleanField(required=False)
    friday = forms.BooleanField(required=False)
    saturday = forms.BooleanField(required=False)
    sunday = forms.BooleanField(required=False)
    method = forms.BooleanField(required=False)
    seed = forms.CharField(required=True)
    enabled = forms.BooleanField(required=False)

    # Override the form clean method
    #  - make sure the scan name does not already exist
    #  - make sure at least one port was selected

    def clean(self):
		cleaned_data = super(ModifySScanForm, self).clean()
		hport = cleaned_data.get('hport')
		sport = cleaned_data.get('sport')
		monday = cleaned_data.get('monday')
		tuesday = cleaned_data.get('tuesday')
		wednesday = cleaned_data.get('wednesday')
		thursday = cleaned_data.get('thursday')
		friday = cleaned_data.get('friday')
		saturday = cleaned_data.get('saturday')
		sunday = cleaned_data.get('sunday')

		# Ensure at least one day was selected (just show the error on monday)
		if not monday and not tuesday and not wednesday and not thursday and not friday and not saturday and not sunday:
			self._errors["monday"] = self.error_class(['Select at least one day'])

		# There must be at least an hport or an sport
		if not hport and not sport:
			self._errors["hport"] = self.error_class(['an HTTP or HTTPS port must be defined'])
			self._errors["sport"] = self.error_class(['an HTTP or HTTPS port must be defined'])

		# Return the full collection of cleaned data
		return cleaned_data  


class AddTScanForm(forms.Form):
    """Form for adding a targeted scan"""

    name = forms.CharField(required=True)
    site = forms.CharField(required=True)
    list = forms.FileField(required=True)
    time = forms.TimeField(required=True,input_formats=['%H:%M'])
    monday = forms.BooleanField(required=False)
    tuesday = forms.BooleanField(required=False)
    wednesday = forms.BooleanField(required=False)
    thursday = forms.BooleanField(required=False)
    friday = forms.BooleanField(required=False)
    saturday = forms.BooleanField(required=False)
    sunday = forms.BooleanField(required=False)
    method = forms.BooleanField(required=False)
    enabled = forms.BooleanField(required=False)

    # Override the form clean method
    #  - make sure the file conforms to our standards 
    #  - make sure the scan name does not already exist
    #  - make sure at least one port was selected

    def clean(self):
		cleaned_data = super(AddTScanForm, self).clean()
		name = cleaned_data.get('name')
		list = cleaned_data.get('list')
		monday = cleaned_data.get('monday')
		tuesday = cleaned_data.get('tuesday')
		wednesday = cleaned_data.get('wednesday')
		thursday = cleaned_data.get('thursday')
		friday = cleaned_data.get('friday')
		saturday = cleaned_data.get('saturday')
		sunday = cleaned_data.get('sunday')
        
		# Instantiate a URL validator
		validate = URLValidator()

		# Check all URLs, they must be properly formatted
		if list:
			for line in list:
				# Strip off any new lines or carriage returns
				line = line.rstrip()

				# Check the URL
				try:
					validate(line)
				except ValidationError:
					self._errors["list"] = self.error_class(['Invalid urls in file'])  

		# Ensure the scan name does not already exist
		if Scan.objects.filter(name=name):
			self._errors["name"] = self.error_class(['That name already exists'])

		# Ensure at least one day was selected (just show the error on monday)
		if not monday and not tuesday and not wednesday and not thursday and not friday and not saturday and not sunday:
			self._errors["monday"] = self.error_class(['Select at least one day'])

		# Return the full collection of cleaned data
		return cleaned_data  


class ModifyTScanForm(forms.Form):
    """Form for adding a targeted scan"""

    id = forms.IntegerField(required=True)
    list = forms.FileField(required=False)
    time = forms.TimeField(required=True,input_formats=['%H:%M'])
    monday = forms.BooleanField(required=False)
    tuesday = forms.BooleanField(required=False)
    wednesday = forms.BooleanField(required=False)
    thursday = forms.BooleanField(required=False)
    friday = forms.BooleanField(required=False)
    saturday = forms.BooleanField(required=False)
    sunday = forms.BooleanField(required=False)
    method = forms.BooleanField(required=False)
    enabled = forms.BooleanField(required=False)

    # Override the form clean method
    #  - make sure the file conforms to our standards 
    #  - make sure the scan name does not already exist
    #  - make sure at least one port was selected

    def clean(self):
		cleaned_data = super(ModifyTScanForm, self).clean()
		list = cleaned_data.get('list')
		monday = cleaned_data.get('monday')
		tuesday = cleaned_data.get('tuesday')
		wednesday = cleaned_data.get('wednesday')
		thursday = cleaned_data.get('thursday')
		friday = cleaned_data.get('friday')
		saturday = cleaned_data.get('saturday')
		sunday = cleaned_data.get('sunday')
        
		# Instantiate a URL validator
		validate = URLValidator()

		# Check all URLs, they must be properly formatted
		if list:
			for line in list:
				# Strip off any new lines or carriage returns
	 			line = line.rstrip()

				# Check the URL
				try:
					validate(line)
				except ValidationError:
					self._errors["list"] = self.error_class(['Invalid urls in file'])  

		# Ensure at least one day was selected (just show the error on monday)
		if not monday and not tuesday and not wednesday and not thursday and not friday and not saturday and not sunday:
			self._errors["monday"] = self.error_class(['Select at least one day'])

		# Return the full collection of cleaned data
		return cleaned_data  


class URLListForm(forms.Form):
	"""Form for querying a URL list"""

	id=forms.IntegerField(required=True)


class DeleteScanForm(forms.Form):
	"""Form for deleting a scan"""

	id=forms.IntegerField(required=True)
     